;
;  Calculates the size required to display a Gadget properly.
;
;  Supported Gadgets:
;    Button, Checkbox, Option, Text, String, ComboBox, Image
;
;  Note:
;    For Gadgets with variable content (String, ComboBox), only the returned height
;    is useful, as the width will only be an absolute minimum value.
;
;  The 'Flags' parameter gives gadget flags to include in the calculation.
;  Currently only #PB_Text_Border makes a difference there.   
;

CompilerIf Defined(Max, #PB_Procedure) = 0
  Procedure Max(a, b)
    If a > b
      ProcedureReturn a
    Else
      ProcedureReturn b
    EndIf
  EndProcedure
CompilerEndIf

CompilerIf #PB_Compiler_OS = #PB_OS_Linux
  Structure PB_Gadget
    *Gadget.GtkWidget
    *Container.GtkWidget
    *VT
    UserData.i
    GadgetData.i[4]
  EndStructure
CompilerEndIf

CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
  Structure OSX_Rect
    top.w
    left.w
    bottom.w
    right.w
  EndStructure
 
  #noErr = 0
CompilerEndIf


; Stores the result in *Width\w and *Height\w
;
Procedure GetRequiredSize(Gadget, *Width.Word, *Height.Word, Flags = 0)

  CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Windows
 
    DC = GetDC_(GadgetID(Gadget))
    oldFont = SelectObject_(DC, GetGadgetFont(Gadget))
    Size.Size
 
    Select GadgetType(Gadget)
   
      Case #PB_GadgetType_Text
        Text$ = RemoveString(GetGadgetText(Gadget), Chr(10))
        count = CountString(Text$, Chr(13)) + 1
        empty = 0
        maxheight = 0
        For index = 1 To count
          Line$ = StringField(Text$, index, Chr(13))
          If Line$ = ""
            empty + 1
          Else
            GetTextExtentPoint32_(DC, @Line$, Len(Line$), @LineSize.SIZE)
            Size\cx = Max(Size\cx, LineSize\cx)
            Size\cy + LineSize\cy
            maxheight = Max(maxheight, LineSize\cy)
          EndIf
        Next index           
        Size\cy + empty * maxheight 
       
        If Flags & #PB_Text_Border
          Size\cx + GetSystemMetrics_(#SM_CXEDGE) * 2
          Size\cy + GetSystemMetrics_(#SM_CYEDGE) * 2
        Else           
          Size\cx + 2
          Size\cy + 2
        EndIf

      Case #PB_GadgetType_CheckBox, #PB_GadgetType_Option
        Text$ = GetGadgetText(Gadget)
        GetTextExtentPoint32_(DC, @Text$, Len(Text$), @Size.SIZE)
        Size\cx + 20
        Size\cy = Max(Size\cy+2, 20)
       
      Case #PB_GadgetType_Button
        Text$ = GetGadgetText(Gadget)
        GetTextExtentPoint32_(DC, @Text$, Len(Text$), @Size.SIZE)
        Size\cx + GetSystemMetrics_(#SM_CXEDGE)*2
        Size\cy = Max(Size\cy+GetSystemMetrics_(#SM_CYEDGE)*2, 24)
        Size\cx + 10
       
      Case #PB_GadgetType_String
        Text$ = GetGadgetText(Gadget) + "Hg"
        GetTextExtentPoint32_(DC, @Text$, Len(Text$), @Size.SIZE)
        Size\cx = GetSystemMetrics_(#SM_CXEDGE)*2
        Size\cy = Max(Size\cy+GetSystemMetrics_(#SM_CXEDGE)*2, 20)
       
      Case #PB_GadgetType_ComboBox
        GetTextExtentPoint32_(DC, @"Hg", 2, @Size.SIZE)
        Size\cy = Max(Size\cy + 8, 21)
        Size\cx = Size\cy 
       
      Case #PB_GadgetType_Image
        Size\cx = GadgetWidth(Gadget)
        Size\cy = GadgetHeight(Gadget)
       
    EndSelect
   
    SelectObject_(DC, oldFont)
    ReleaseDC_(GadgetID(Gadget), DC)
    *Width\w  = Size\cx
    *Height\w = Size\cy
 
  CompilerCase #PB_OS_Linux
 
    *Gadget.PB_Gadget = IsGadget(Gadget)
   
    If *Gadget And *Gadget\Container And GadgetType(Gadget) <> #PB_GadgetType_ComboBox
      gtk_widget_size_request_(*Gadget\Container, @RealSize.GtkRequisition)
      gtk_widget_set_size_request_(*Gadget\Container, -1, -1)
      gtk_widget_size_request_(*Gadget\Container, @Size.GtkRequisition)     
      gtk_widget_set_size_request_(*Gadget\Container, RealSize\Width, RealSize\Height)
    Else
      gtk_widget_size_request_(GadgetID(Gadget), @RealSize.GtkRequisition)
      gtk_widget_set_size_request_(GadgetID(Gadget), -1, -1)             
      gtk_widget_size_request_(GadgetID(Gadget), @Size.GtkRequisition)   
      gtk_widget_set_size_request_(GadgetID(Gadget), RealSize\Width, RealSize\Height)
    EndIf
   
    If GadgetType(Gadget) = #PB_GadgetType_ComboBox Or GadgetType(Gadget) = #PB_GadgetType_String
      *Width\w  = 20
    Else
      *Width\w  = Size\Width
    EndIf
    
    *Height\w = Size\Height   

  CompilerCase #PB_OS_MacOS
 
    Type = GadgetType(Gadget)
   
    If Type = #PB_GadgetType_Image   
      *Width\w = GadgetWidth(Gadget)
      *Height\w = GadgetHeight(Gadget)
     
    ElseIf Type = #PB_GadgetType_Text
      realwidth   = GadgetWidth(Gadget)
     
      *Width\w = 40
      *Height\w = 20     
     
      ResizeGadget(Gadget, #PB_Ignore, #PB_Ignore, 1000, #PB_Ignore)
     
      If GetBestControlRect_(GadgetID(Gadget), @Rect.OSX_Rect, @BaseLine.w) = #noErr
        Height = Rect\bottom - Rect\top
        If Height > 0
       
          Min = 0
          Max = 1000
         
          While Max > Min+2
            Mid = (Min + Max) / 2
           
            ResizeGadget(Gadget, #PB_Ignore, #PB_Ignore, Mid, #PB_Ignore)
           
            If GetBestControlRect_(GadgetID(Gadget), @Rect.OSX_Rect, @BaseLine.w) <> #noErr
              ProcedureReturn
            EndIf
           
            If Rect\bottom - Rect\top > Height
              Min = Mid
            Else
              Max = Mid
            EndIf
          Wend
         
          *Width\w = Rect\right - Rect\left + 2
          *Height\w = Max(Height, 20)
        EndIf
         
      EndIf
     
      ResizeGadget(Gadget, #PB_Ignore, #PB_Ignore, realwidth, #PB_Ignore)

    Else
      If GetBestControlRect_(GadgetID(Gadget), @Rect.OSX_Rect, @BaseLine.w) = #noErr
        *Width\w = Rect\right - Rect\left
        *Height\w = Max(Rect\bottom - Rect\top, 20)
       
        If Type = #PB_GadgetType_Button Or Type = #PB_GadgetType_String
          *Height\w = Max(*Height\w, 24)       
        EndIf       
      Else
        *Width\w = 40
        *Height\w = 20
      EndIf
     
      If Type = #PB_GadgetType_String Or Type  = #PB_GadgetType_ComboBox       
        *Width\w = 30
      EndIf
    EndIf
  CompilerEndSelect
EndProcedure

; convinience wrappers if only one size is needed
;
Procedure.w GetRequiredWidth(Gadget, Flags = 0)
  Protected Width.w, Height.w
  GetRequiredSize(Gadget, @Width, @Height, Flags)
  ProcedureReturn Width
EndProcedure

Procedure.w GetRequiredHeight(Gadget, Flags = 0)
  Protected Width.w, Height.w
  GetRequiredSize(Gadget, @Width, @Height, Flags)
  ProcedureReturn Height
EndProcedure

; IDE Options = PureBasic 4.40 Beta 6 (Linux - x86)
; CursorPosition = 8
; Folding = -
; EnableXP